/*=========================================================================
	UberSim Source Code Release
	-------------------------------------------------------------------------
	Copyright (C) 2002 Manuela Veloso, Brett Browning, Mike Bowling,
	James Bruce; {mmv, brettb, mhb, jbruce}@cs.cmu.edu
	Erick Tryzelaar {erickt}@andrew.cmu.edu
	School of Computer Science, Carnegie Mellon University
	-------------------------------------------------------------------------
	This software is distributed under the GNU General Public License,
	version 2.  If you do not have a copy of this licence, visit
	www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
	Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
	in the hope that it will be useful, but WITHOUT ANY WARRANTY,
	including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	-------------------------------------------------------------------------*/

#include <stdio.h>

#include "mmgr.h"

#include "Engine.h"
#include "Entity.h"
#include "Event.h"
#include "Spatial.h"
#include "Timer.h"

Timer* Timer::getInstance ()
{
	static Timer instance;

	return &instance;
}

Timer::Timer  ()
{
	isInitialized = false;
	isShutdown    = true;
}

Timer::~Timer ()
{
}

void Timer::initialize ()
{
	if (!isInitialized)
	{
		isInitialized = true;
		isShutdown    = false;
	}
}

void Timer::shutdown ()
{
	if (!isShutdown)
	{
		isShutdown    = true;

		clearEvents ();
		
		isInitialized = false;
	}
}

void Timer::addEvent (Entity* entity, Event* event, Real deltaTime)
{
	Engine* engine = Engine::getInstance ();
	
	queue.push (Timer::Node (entity, event, deltaTime + (engine->getFrameCount ()) / engine->getTargetFps ()));
}

void Timer::clearEvents ()
{	
	while (!queue.empty ())
	{
		const Node& node = queue.top ();

		delete node.event;
		
		queue.pop ();
	}
}

void Timer::beginFrame ()
{
}

void Timer::frame ()
{
	if (!queue.empty ())
	{
		Engine* engine = Engine::getInstance ();
		
		Real currentTime = engine->getFrameCount() / engine->getTargetFps ();

		while (!queue.empty () && queue.top ().endTime <= currentTime)
		{
			const Node& node = queue.top ();
	
			node.entity->handleEvent (node.event);
			
			queue.pop ();
		}
	}
}

void Timer::endFrame ()
{
}

Timer::Node::Node (Entity* entity, Event* event, Real endTime)
{
	this->entity  = entity;
	this->event   = event;
	this->endTime = endTime;
}

bool Timer::Node::operator > (const Timer::Node& node) const
{
	return endTime > node.endTime;
}
